package biz.datalk.industrialland.common.util;

import biz.datalk.commons.utils.json.JsonUtil;
import biz.datalk.industrialland.common.def.CommonConstant;
import biz.datalk.industrialland.common.result.UnifyResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

/**
 * 请求错误处理工具类
 *
 * @author tarofang@163.com
 * @date 2020-01-14
 */
@Slf4j
public class ReqErrUtil {

    public static void reqPrint(HttpServletRequest request, HttpServletResponse response, String rsCode, String rsCause, String errPagePath, boolean isForward) {
        String token = request.getHeader(CommonConstant.ACCESS_TOKEN);
        if (StringUtils.isNotEmpty(token)) {
            reqApi(response, rsCode, rsCause);
            return;
        }

        if (StringUtils.equalsIgnoreCase(request.getHeader(CommonConstant.X_REQ_TYPE), CommonConstant.X_REQ_TYPE_VALUE)) {
            reqApi(response, rsCode, rsCause);
        } else {
            reqPage(request, response, rsCode, rsCause, errPagePath, isForward);
        }
    }

    public static void reqPrint(HttpServletRequest request, HttpServletResponse response, String rsCode, String rsCause, String errPagePath) {
        reqPrint(request, response, rsCode, rsCause, errPagePath, Boolean.FALSE);
    }

    /** 请求的api */
    public static void reqApi(HttpServletResponse response, String rsCode, String rsCause) {
        PrintWriter pw = null;
        try {
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            // application/json;charset=UTF-8
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            // 输出错误信息
            String result = JsonUtil.getJsonFromObject(UnifyResult.fail(rsCode, rsCause));
            pw = response.getWriter();
            pw.write(result);
            pw.flush();
        } catch (IOException e) {
            log.warn(e.getMessage(), e);
        } finally {
            if (pw != null) {
                pw.close();
            }
        }
    }

    /** 请求的页面, 返回错误页面 */
    public static void reqPage(HttpServletRequest request, HttpServletResponse response, String rsCode, String rsCause, String errPagePath, boolean isForward) {
        try {
            // 转发
            if (isForward) {
                request.setAttribute("rsCode", rsCode);
                request.setAttribute("rsCause", rsCause);
                request.getRequestDispatcher(getContextPath(request).concat(errPagePath)).forward(request, response);
                return;
            }

            // 重定向
            WebUtils.setSessionAttribute(request, "rsCode", rsCode);
            WebUtils.setSessionAttribute(request, "rsCause", rsCause);
            response.sendRedirect(getContextPath(request).concat(errPagePath));
        } catch (ServletException | IOException e) {
            log.warn(e.getMessage(), e);
        }
    }

    public static String getContextPath(HttpServletRequest request) {
        String contextPath = request.getContextPath();
        contextPath = StringUtils.equals(contextPath, "/") ? StringUtils.EMPTY : contextPath;
        return contextPath;
    }

    /**
     * 判定改请求是 返回页面 还是数据
     *
     * @param request
     * @return true - 返回数据  false - 返回页面
     */
    public static boolean isReturnApi(HttpServletRequest request) {
        // 默认返回 数据  当前请求在系统中不存在时，默认返回数据
        HandlerMethod handlerMethod = SpringContextUtils.getRequestHandlerMethod(request);
        if (handlerMethod == null) {
            return true;
        }
        Class<?> beanType = handlerMethod.getBeanType();
        Method method = handlerMethod.getMethod();

        if (beanType.isAnnotationPresent(Controller.class)) {
            return method.isAnnotationPresent(RequestBody.class);
        }

        if (beanType.isAnnotationPresent(RestController.class)) {
            return !method.getReturnType().equals(ModelAndView.class);
        }

        return false;
    }

}
